(preact-iso): Use pushState/ replaceState for useLocation().route method#413
(preact-iso): Use pushState/ replaceState for useLocation().route method#413piotr-cz wants to merge 9 commits intopreactjs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: 3d0d9f4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
developit
left a comment
There was a problem hiding this comment.
It looks like this was already supported?
route('/url', true)
(admittedly, push=true might be a better default)
| path: string; | ||
| query: Record<string, string>; | ||
| route: (url: string) => void; | ||
| route: (url: string | { url: string, replace?: boolean }) => void; |
There was a problem hiding this comment.
Wondering if we can use (url, replace) here? That would match preact-router.
|
@developit wmr/packages/preact-iso/router.js Lines 44 to 51 in 58f1bff Probably we would have to refactor router code to not use reducer in this case (which may be not a bad idea to handle history outside/ without reducer). |
|
I prefer |
|
I've created new PR in #424 to fix the bug with location change after using After it's resolved it will be easier to move forward with adding an option such as |
|
Nice - thanks for pulling that out, just merged it. |
packages/preact-iso/router.js
Outdated
| } else if (url instanceof PopStateEvent) { | ||
| url = location.pathname + location.search; | ||
| // manual invocation: route({ path, replace }) | ||
| } else if (typeof url === 'object') { |
There was a problem hiding this comment.
Here's what I'd suggest, in order to preserve the duck typing (as mentioned in previous comment):
const UPDATE = (state, update) => {
/** @type {boolean|undefined} - History state update strategy */
let push, url;
if (!update || typeof update === 'string') {
url = update;
push = true;
}
else if (update.type === 'click') {
// user click
// @ts-ignore-next
const link = update.target.closest('a[href]');
if (!link || link.origin != location.origin) return state;
update.preventDefault();
url = link.pathname + link.search + link.hash;
push = true;
}
else if (update.type === 'popstate') {
// navigation
url = location.pathname + location.search + location.hash;
}
else {
// manual invocation: route(url) or route({ url, replace })
url = update.url || update;
push = !url.replace;
}
if (push === true) history.pushState(null, '', url);
else if (push === false) history.replaceState(null, '', url);
return url;
}There was a problem hiding this comment.
Should we allow passing a value that evaluates to false (undefined/ null) with route method?
If so, then should it be added to history?
if (!update || typeof update === 'string') {
// ^When the update is not either string or event I'd say it must be an object?
else {
// manual invocation: route(url) or route({ url, replace })
url = update.url || update;
// ^There was a problem hiding this comment.
I've updated PR with code you suggested, adapting to eslint/ prettier rules
There was a problem hiding this comment.
@developit
What do you think about my comments above?
# Conflicts: # packages/preact-iso/router.js
|
I've updated PR to use code suggested in #413 (comment) However I'm not happy with the |
|
@piotr-cz I think we might be able to create a wrapper function in the provider that swaps the argument signature: - const [url, route] = useReducer(UPDATE, location.pathname + location.search);
+ const [url, doRoute] = useReducer(UPDATE, location.pathname + location.search);
+ const route = useCallback((url, replace) => doRoute({ url, replace }), []);It might even be possible to simplify the history event handling this way too. |
|
@developit |
|
Just one question: |
|
I'd go for patch yea |
At this moment when using
useLocation().route('/foobar')window location doesn't change: neitherhistory.pushStatenorhistory.replaceStatemethod is used.This pull request
pushState.replaceStateOriginally the useReducer hook dispatcher had a third
pushargument, but dispatchers consume only two arguments.wmr/packages/preact-iso/router.js
Line 4 in 58f1bff
I'm not sure if I should bump patch or minor version with changeset?